<template>
  <div id="wrap" class="init">
    <div id="bg-circle">
      <div></div>
      <div></div>
      <div></div>
    </div>
    <div class="conf-wrap">
      <div class="line">
        <div class="option">
          <button class="btn-data-input" disabled>导入json</button>
          <input class="data-input" type="file" file="">

          <button class="btn-data output" @click="() => {
            exportJson(questionSet, expFile)
          }">导出json</button>
          <input type="text" :value="conf.subject + '.json'" @change="event => {
            expFile = event.target.value
          }">
          <button class="btn-data output" @click="() => {
            resolveQuestions()
            exportJson(QKVL, 'final_' + conf.subject + '.json')
          }">导出已处理json</button>
          <input type="text" :value="'final_' + conf.subject + '.json'" disabled>
          <button @click="clearLocalStorage">清空缓存</button>
        </div>
      </div>

      <div class="line">
        <div class="option">
          <span>token: </span>
          <input class="ipt-long" type="text" :value="conf.token" @change="event => {
            conf.token = event.target.value

            sssave('__token', event.target.value);
          }">
        </div>
        <div class="option">
          <span>端口:</span>
          <input type="number" :value="conf.port" :disabled="conf.socket" @change="event => {
            conf.port = event.target.value
          }">
        </div>
        <button @click="linkWs" :disabled="conf.socket">连接服务</button>
      </div>

      <div class="line">
        <div class="option">
          <span>目标题目数: </span>
          <input class="ipt-long" type="number" :value="conf.target" @change="event => {
            conf.target = event.target.value
          }" step="100">
        </div>
        <div class="option">
          <span>单次获取题目数: </span>
          <input class="ipt-long" type="number" :value="conf.size" @change="event => {
            conf.size = event.target.value
          }" step="1">
        </div>
      </div>

      <div class="line">
        <div class="option">
          <span>科目: </span>
          <select name="subject" id="" @change="event => {
            conf.subject = event.target.value
            readLocal()
          }">
            <option value="全部">全部</option>
            <option value="大学信息技术">大学信息技术</option>
            <option value="数字媒体基础">数字媒体基础</option>
            <option value="数据分析">数据分析</option>
            <option value="人工智能">人工智能</option>
          </select>
        </div>
      </div>

      <div class="line">
        <div class="option">
          <span>执行间隔: </span>
          <input type="number" min="500" :value="conf.interval" @change="event => {
            conf.interval = event.target.value
          }" step="50">
        </div>
        <button @click="start">开始执行</button>
        <button @click="stop">停止执行</button>
      </div>
    </div>

    <div id="processBar" v-if="maxPage">
      <div class="current" :style="'width:' + (maxPage + 1) / conf.target * 100 + '%;'">
        <span>{{ maxPage + 1 }} / {{ conf.target }}</span>
      </div>
    </div>

    <div id="content" @wheel="scrollText">
      <ul>
        <li v-for="k in displaySet" class="question-text">
          <span>{{ k.id }}. </span>
          <p>{{ k.question }}</p>
        </li>
      </ul>
    </div>

    <div id="pageBtn" class="line">
      <div class="optioin">
        <button @click="stat.top--">&lt;</button>
        <input type="text" :value="`${stat.top} / ${maxPage + 1}`" @input="event => {
          // stat.top = event.target.value

        }" step="1" min="0" disabled>
        <button @click="stat.top++">&gt;</button>
        <!-- <button>跳转</button> -->
      </div>
    </div>
  </div>


  <div id="temp" style="height: 10rem;width:100%">
    <!-- <a href="" ></a> -->
  </div>
</template>

<script setup>
import { ref, onMounted, watch } from 'vue'
import { msg } from './assets/script/function.lib'

import { ws } from './assets/script/websocket'

import he from 'he'

const conf = ref({
  port: 4403,
  interval: 600,
  target: 1000,
  size: 10,
  subject: '全部',
  socket: null,
  token: null
})

const stat = ref({
  top: 0,
  display: 30
})

const expFile = ref(`export_${conf.value.subject}.json`)

const questionSet = ref({})
const displaySet = ref([])

const running = ref(false)

const maxPage = ref(0)

const questions = ref({
  // 单选
  CQ: [],
  // 填空
  Fill: [],
  JQ: [],
  // 判断对
  JQ_T: [],
  // 判断错
  JQ_F: []
})

const QKVL = ref([])

function linkWs() {
  ws(conf.value.port, {
    type: '敬明天'
  })
    .then(res => {
      conf.value.socket = res

      msg({
        text: `**Websocket** 连接成功，端口\`${conf.value.port}\``,
        delay: 3000
      })

    })
    .catch(err => {
      msg({
        text: `连接失败\t<font color="red">${err}</font>`
      })
    })
}

let loopTimes = 0

function start() {
  try {
    for (let k in conf.value) {
      if (!conf.value[k]) throw `非法的参数 ${k}`
    }
  } catch (err) {
    msg({
      text: `执行出错或有参数未填写\t<font color="red">${err}</font>`
    })
  }

  running.value = false
  getData()
}

function getData() {
  if (!running.value) {
    loopTimes++
    msg(`第${loopTimes}次执行`);

    ws(conf.value.socket, {
      type: 'GET',
      token: conf.value.token,
      size: conf.value.size,
      subject: conf.value.subject
    }).then(res => {
      // console.log(res);

      try {
        const data = res.msg.msg.data;

        data.item_list.forEach((item, i) => {
          if (!questionSet.value[item.id]) {
            const stat = data.stat_list[i],
              status = data.status_list[i]

            if (stat.id == status.id && status.id == item.id) {
              delete stat.id
              delete status.id
              questionSet.value[item.id] = {
                ...item,
                stat,
                status
              }
            } else {
              console.warn(data);
            }

          }
        })

        // console.log(questionSet.value);

        localStorage.setItem("questions_" + conf.value.subject, JSON.stringify(questionSet.value))

        maxPage.value = Object.keys(questionSet.value).length - 1


        // 
        clearTimeout(window.getData_timer)
        if (Object.keys(questionSet.value).length < conf.value.target) {
          window.getData_timer = setTimeout(() => {
            getData()
          }, conf.value.interval)
        } else {

          // console.log(Object.keys(questionSet.value).length > conf.value.target);

          msg({
            text: `目标已达成`,
            delay: 5000
          })
        }



      } catch (err) {
        console.error(err);
        msg({
          text: `解析出错 <font color="red">${err}</font>`
        })

        // 出错后5分钟继续
        clearTimeout(window.getData_timer)
        window.getData_timer = setTimeout(() => getData(), 1000 * 60 * 5)
      }

    })
  }
}

function stop() {
  running.value = true
  delete window.getData_timer
  clearTimeout(window.getData_timer)

  msg({
    text: `**GET** 操作已取消`
  })
}

function scrollText(event) {
  // console.log(event.deltaY);
  convertToArr(event.deltaY)
}

function readLocal() {
  let local = localStorage.getItem("questions_" + conf.value.subject)

  questionSet.value = {}
  displaySet.value = {}

  if (local) {
    questionSet.value = JSON.parse(local)

    convertToArr()

    maxPage.value = Object.keys(questionSet.value).length - 1
    msg({
      text: `缓存解析成功，数量: ${Object.keys(questionSet.value).length}`
    })
  }
}

onMounted(() => {

  // 转义 HTML 字符
  // const encoded = he.encode('<p>Hello World</p>');
  // console.log(encoded); // &lt;p&gt;Hello World&lt;/p&gt;

  // 解码 HTML 字符
  // const decoded = he.decode('&lt;p&gt;Hello World&lt;/p&gt;');
  // console.log(decoded); // <p>Hello World</p>
  // linkWs(4403)
  if (sessionStorage.getItem('__token')) {
    conf.value.token = sessionStorage.getItem('__token')
  }

  readLocal()


  watch(questionSet.value, () => {
    convertToArr()

    stat.value.top = 0
  })

  watch(stat.value, (newVal, oldVal) => {
    // console.log(newVal, oldVal);

    const maxPage = Object.keys(questionSet.value).length - 1

    // newVal.top = newVal.top < 0 ? 0 : newVal.top
    newVal.top = newVal.top >= maxPage ? maxPage : newVal.top


    // if (oldVal.top != newVal.top) {
    //   console.log(1111111);


    // }
    convertToArr()

  })


  setTimeout(() => {

    msg({
      text: '页面加载完成',
      delay: 6000
    })
  }, 100)

  // 动画
  setTimeout(() => {
    $('.init').removeClass('init')
  }, 100)
})

function sssave(name, data) {
  sessionStorage.setItem(name, data)

}

function clearLocalStorage() {
  localStorage.clear()

  location.reload()
}

function convertToArr(offset = 0) {
  displaySet.value = {}
  let delta = stat.value.top + offset / 20
  stat.value.top = delta <= 0 ? 0 : delta
  // let top = delta <= 0 ? 0 : delta
  // console.log(stat.value , offset / 20);

  // Object.keys(questionSet.value).slice(delta, stat.value.display + delta).forEach(e => {
  Object.keys(questionSet.value).slice(stat.value.top, stat.value.display + stat.value.top).forEach(e => {
    displaySet.value[e] = questionSet.value[e]
  })
}

function exportJson(data, name) {
  let jsonData = JSON.stringify(data);
  let blob = new Blob([jsonData], { type: 'application/json' });
  let url = URL.createObjectURL(blob);

  let a = document.createElement('a');
  a.href = url;
  a.download = name;
  a.click();
  URL.revokeObjectURL(url);
}

function resolveQuestions() {
  for (let k in questionSet.value) {
    const data = questionSet.value[k]
    // console.log(data.type, data.type == 1)

    try {

      // 题目难度 [0,1] 映射到[0,5]
      const diff = Math.round(data.stat.difficulty * 5)
      const _qus = he.encode(data.question),
        _ans = he.encode(data.answer)

      if (data.type == 1) {
      }

      switch (data.type) {
        case 0:
          // 填空
          questions.value.Fill.push([
            'fill', _qus,
            _ans, diff
          ])

          break;
        case 1:
          questions.value.CQ.push([
            'CQ', _qus,
            [he.encode(data.choiceA), he.encode(data.choiceB), he.encode(data.choiceC), he.encode(data.choiceD)],
            _ans.toUpperCase().charCodeAt() - 64,
            diff
          ])
          break;
        case 2:
          // 判断
          questions.value.JQ.push([
            'JQ', _qus, _ans == 'true' ? 1 : 0, diff
          ])

          break;

        default:
          break;
      }
    } catch (err) {
      msg({
        text: `解析出错: <font color="red">${err}</front>`,
        delay: 8000
      })
    }
  }

  getFinalQL()
  // console.log(questionSet.value);

  // console.log(QKVL.value);


}

function getFinalQL() {
  QKVL.value = [
    [
      "elem",
      "\n\n" + conf.value.subject,
      [1.6, 400, "0.32rem"],
      [
        ["position", "relative"], ["left", "10%"], ["width", "90%"],
        ["textShadow", "rgb(0 0 255 / 20%) 0.1rem 0.1rem 0.24rem, rgb(51 51 34 / 13%) 0.16rem 0.16rem 0.32rem"],
        ["addClassName", "questionsPart"]]
    ]
  ]


  addQType('CQ', '单选')
  addQType('JQ', '判断')
  addQType('Fill', '填空')

  console.log(questionSet.value)
  console.log(QKVL.value)
}


function addQType(type, tit) {
  // 测试仅获取前十
  // const list = questions.value[type].slice(0, 10)
  const list = questions.value[type]
  if (list.length) {
    QKVL.value = [...QKVL.value,
    ['elem', '\n\t ' + tit, [0.96, 800],
      [
        ['MB', '0.32rem']
      ]
    ], ...list]
  }
}

</script>

<style scoped lang="less">
@import url(./assets/style/main.css);
@import url(./assets/style/background.css);
</style>
